<?php

/**
 * contact : 刘经理 19326416371
 * company : 版权所属 四川北星惯牌科技有限公司
 **/

namespace app\common\manager\prepay\gateway;

use addons\epay\library\Service;
use app\common\manager\OrderManager;
use app\common\manager\PayLogManager;
use app\common\manager\UserAccountManager;
use app\common\model\Goods;
use app\common\model\Level;
use app\common\model\Order;
use app\common\model\PurchaseRecord;
use app\common\model\User;
use app\common\model\UserAccount;
use app\common\model\VipExpires;
use think\Db;
use think\Exception;

class Purchase
{
    CONST METHOD = 'Purchase';

    CONST TYPE_ALIPAY = 1;
    CONST TYPE_WECHAT = 2;
    public function order($user,$request,$trans=true)
    {
        if ($trans)
            Db::startTrans();
        try {
            $prePayment = null;
            $type = $request['type'] ?? 'wechat';
            $method = $request['method'] ?? 'JSAPI';
            $goods_id = $request['goods_id'];
            $is_balance = $request['isBalance'];
            if(!$goods_id){
                throw new Exception('请正确访问');
            }

            $goodsInfo = Goods::where('g_id',$goods_id)->find();
            if(!$goodsInfo){
                throw new Exception('商品信息不存在，无法购买');
            }

            if ($goodsInfo['shelves'] == Goods::SHELVES_NO){
                throw new Exception('当前商品已下架，无法购买');
            }

            $orderId = orderNum();
            $purchaseOrder = [
                'order' => $orderId,
                'user_id' => $user->id,
                'amount' => bcadd($goodsInfo['price'],0,2),
                'goods_id' => $goods_id,
                'product_id' => $goodsInfo['pdu_id'],
                'goods_price' => bcadd($goodsInfo['price'],0,2),
                'goods_detail' => serialize($goodsInfo),
                'type' => $type,
                'is_balance'=>$request['isBalance'] ? PurchaseRecord::IS_BALANCE_YES : PurchaseRecord::IS_BALANCE_NO,
                'create_time' => time(),
                'update_time' => time()
            ];

            $purchaseOrderInfo = PurchaseRecord::create($purchaseOrder);
            if (!$purchaseOrderInfo) {
                throw new Exception('充值订单创建失败');
            }

            if ($purchaseOrderInfo->amount < 0.01) {
                throw new Exception('订单金额有误，无法创建订单');
            }
            $time_expire = config('app.time_expire') ?? 5;
            $time_expire = bcadd(time(), bcmul($time_expire, 60));
            if ($type == 'wechat') {
                $time_expire = date('YmdHis', $time_expire);
            } else if ($type == 'alipay') {
                $time_expire = date('Y-m-d H:i:s', $time_expire);
            }
            $money = bcadd($purchaseOrderInfo->amount, 0, 2);
            $data['order'] = $orderId;
            $data['user_id'] = $user->id;
            $data['order_money'] = $money;
            $data['relation_id'] = $purchaseOrderInfo->id;
            $data['expire_time'] = strtotime($time_expire);
            $data['ct_date'] = time();
            $result = OrderManager::Order($user, $data, \app\common\model\Order::TYPE_EXPRESS, false);
            //file_put_contents('pur.txt','$result:'.json_encode($result),FILE_APPEND);
            $result1 = PayLogManager::record(['user_id' => $user->id, 'method' => self::METHOD, 'type' => $type == 'alipay' ? self::TYPE_ALIPAY : self::TYPE_WECHAT, 'order' => $orderId, 'money' => $money, 'create_time' => time()],false);
            //file_put_contents('pur.txt','$result1:'.json_encode($result1),FILE_APPEND);
            $returnUrl = \config('app.returnUrl');
            if ($type == 'wechat') {
                $notifyUrl = \config('app.notifyWechatUrl');
            } else if ($type == 'alipay') {
                $notifyUrl = \config('app.notifyAlipayUrl');
            }

            if ($is_balance && $result['code']==OrderManager::$successCode){
                $userAccount = UserAccount::where('user_id',$user->id)->find();
                if (!$userAccount){
                    throw new Exception('当前用户账户信息有误，无法使用此功能');
                }
                $result2 = UserAccountManager::money($user->id,$money,UserAccountManager::CHANGE_TYPE_PAYMENT,time(),UserAccountManager::TYPE_VOUCHER,['relation_id'=>$result['data']['id']],false);
                #file_put_contents('pur.txt','$result2:'.json_encode($result2),FILE_APPEND);
                if ($result2['code']!=UserAccountManager::$successCode){
                    throw new Exception($result2['message']);
                }
                $resUpdate = ['pay_state'=>Order::PAY_STATE_SUCCESS,'pay_date'=>time(),'up_date'=>time()];
                $resultOrder = OrderManager::modify($result['data']['id'],$resUpdate,false);
                if ($resultOrder['code']!=OrderManager::$successCode){
                    throw new Exception($resultOrder['message']);
                }

                $purchaseOrderInfo->update_time = time();
                $purchaseOrderInfo->status = PurchaseRecord::STATUS_SUCCESS;
                $purchaseOrderInfo->save();

                $levelInfo = Level::where('vl_id',$goodsInfo['level_id'])->find();
                if (!$levelInfo){
                    throw new Exception('当前订单等级信息不存在');
                }
                $vipExpiresInfo = VipExpires::where('user_id',$purchaseOrderInfo->user_id)->where('level',$levelInfo['vl_id'])->find();
                $results = false;
                $startTime = strtotime(date('Y-m-d'));
                if(!$vipExpiresInfo){
                    $insert = [
                        'user_id'=>$purchaseOrderInfo->user_id,
                        'level'=>$levelInfo['vl_id'],
                        'level_sort'=>$levelInfo['sort'],
                        'start_date'=>$startTime,
                        'end_date'=>$startTime+($goodsInfo['validity_period']*3600*24),
                        'create_time'=>time(),
                    ];
                    $results = VipExpires::create($insert);
                }else{
                    $results = VipExpires::where('user_id',$purchaseOrderInfo->user_id)->where('level',$levelInfo['vl_id'])->update([
                        'end_date'=>Db::raw('end_date + '.($goodsInfo['validity_period']*3600*24)),
                        'update_time'=>time()
                    ]);
                }

                if (!$results){
                    throw new Exception('当前订单更新失败');
                }

                $vipUser = VipExpires::where('user_id',$purchaseOrderInfo->user_id)->order('level_sort desc')->find();
                if(!User::where('id',$purchaseOrderInfo->user_id)->update([
                    'temp_level'=>$vipUser['level'] ?? $levelInfo['vl_id'],
                    'updatetime'=>time()
                ])){
                    throw new Exception('用户信息更新失败');
                }

                if ($trans)
                    Db::commit();
                $prePayment = null;

            }else{
                if ($result['code'] == OrderManager::$successCode && $result1['code'] == PayLogManager::$successCode) {
                    $result['data']['time_expire'] = strtotime($time_expire);
                    if ($trans)
                        Db::commit();
                    $prePayment = Service::submitOrder($money, $data['order'], $type, \app\common\model\Order::TYPE_ARRAY[\app\common\model\Order::TYPE_EXPRESS]['name'], $notifyUrl, $returnUrl, $method, $user->open_id, $time_expire, ['relation_id' => $purchaseOrderInfo->id]);
                    //print_r($prePayment);
                    if ($result1['data']['id']) {
                        $id = $result1['data']['id'];
                        $update = ['request' => serialize($prePayment)];
                        PayLogManager::modify($id, $update);
                    }
                } else {
                    throw new Exception($result['message'] . '或' . $result1['message']);
                }
            }
            if ($trans)
                Db::commit();
            return ['code' => 1, 'message' => 'success', 'data' => ['order' => $result['data'], 'pre_payment' => $prePayment]];
        } catch (Exception $exception) {
            if ($trans)
                Db::rollback();
            return ['code' => 0, 'message' => $exception->getMessage().$exception->getLine(), 'data' => null];
        }
    }
}